local io = io
local os = os
local string = string
local tostring = tostring
local debug = debug
local io_open = io.open
local string_format = string.format
local debug_traceback = debug.traceback
local ngx = ngx
local n_ERR = ngx.ERR

local mis_network = nil
local mis_config = nil

--------------------------------------------------------------
local mis_log = {
    s_name = string.match(debug.getinfo(1).short_src, '.*/(.*).lua'); -- 模块名称
    t_logLevel = {
        n_debug = 1;
        n_warning = 2;
        n_must = 3;
        n_error = 4;
    };
    n_curLevel = 0;
    s_path = './logs/miniw/';
    s_remote_path = 'logs/miniw/';
    b_logBySay = false;
    t_fd = {};
}
local this = mis_log
this.n_curLevel = this.t_logLevel.n_debug

local function get_fd(s_name)
    local s_filePath = this.s_path .. s_name .. '.log'
    if this.t_fd[s_filePath] then
        return this.t_fd[s_filePath]
    end
    local u_fd, s_err = io_open(s_filePath, 'a+')
    if not u_fd then
        ngx.log(n_ERR, s_err)
        return
    end
    u_fd:setvbuf('no')
    this.t_fd[s_filePath] = u_fd
    return u_fd
end

--------------------------------------------------------------
-- 说明：模块包含
-- 参数：模块表
this.modules_include = function(t_modules)
    mis_network = t_modules.mis_network
    mis_config = t_modules.mis_config
end

-- 设定日志级别
function this.set_level(n_level)
    if not n_level then
        ngx.log(n_ERR, 'no such t_logLevel : ' .. n_level)
    end
    this.n_curLevel = n_level
end

-- 设定日志输出终端
function this.set_print_terminal(b_)
    this.b_logBySay = b_
end

-- 设定路径
function this.set_path(s_path)
    this.s_path = s_path
end

-- 输出日志
function this.debug(ts_msg)
    if this.n_curLevel > this.t_logLevel.n_debug then return end
    if this.b_logBySay then
        ts_msg = '[' .. ngx.localtime() .. '] ' .. ts_msg .. '<br>'
        ngx.say(ts_msg)
    else
        local u_fd = get_fd('log_debug')
        if not u_fd then return end
        ts_msg = '[' .. ngx.localtime() .. '] ' .. ts_msg .. '\n'
        u_fd:write(ts_msg)
    end
end

-- 输出日志
function this.warning(s_msg)
    if this.n_curLevel > this.t_logLevel.n_warning then return end
    if this.b_logBySay then
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '<br>'
        ngx.say(s_msg)
    else
        local u_fd = get_fd('log_warning')
        if not u_fd then return end
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '\n'
        u_fd:write(s_msg)
    end
end

-- 输出日志
function this.must(s_msg)
    if this.n_curLevel > this.t_logLevel.n_must then return end
    if this.b_logBySay then
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '<br>'
        ngx.say(s_msg)
    else
        local u_fd = get_fd('log_must')
        if not u_fd then return end
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '\n'
        u_fd:write(s_msg)
    end
end

-- 输出日志
function this.error(s_msg)
    if this.n_curLevel > this.t_logLevel.n_error then return end
    if this.b_logBySay then
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '<br>' .. debug_traceback() .. '<br>' ..
            ngx.var.server_addr .. ':' .. ngx.var.server_port .. ngx.var.request_uri
        ngx.say(s_msg)
    else
        local u_fd = get_fd('log_error')
        if not u_fd then return end
        s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '\n' .. debug_traceback()
        u_fd:write(s_msg)
    end
end

-- 输出日志到指定文件，文件不存在则创建
function this.out(s_filename, s_msg)
    local u_fd = get_fd(s_filename)
    if not u_fd then return end
    s_msg = '[' .. ngx.localtime() .. '] ' .. s_msg .. '\n'
    u_fd:write(s_msg)
end

-- 输出日志到"带当前日期后缀的名字的"文件，文件不存在则创建
function this.day(s_filename, s_msg)
    local s_localtime = ngx.localtime()
    s_filename = s_filename .. '_' .. s_localtime:match('(.+) ')
    local u_fd = get_fd(s_filename)
    if not u_fd then return end
    s_msg = '[' .. s_localtime .. '] ' .. s_msg .. '\n'
    u_fd:write(s_msg)
end

-- 输出日志到"带当前日期后缀的名字的"文件，文件不存在则创建
-- 日志内容不包含头部时间
function this.pure_day(s_filename, s_msg)
    local s_localtime = ngx.localtime()
    s_filename = s_filename .. '_' .. s_localtime:match('(.+) ')
    local u_fd = get_fd(s_filename)
    if not u_fd then return end
    u_fd:write(s_msg .. '\n')
end

-- 打印远程日志(mission埋点统一使用远程日志)
function this.remote_day(s_filename, s_msg)
    local s_localtime = ngx.localtime()
    s_filename = s_filename .. '_' .. s_localtime:match('(.+) ')
    s_msg = '[' .. s_localtime .. '] ' .. s_msg

    if  mis_config.s_log_net_url then
        local s_filePath = this.s_remote_path .. s_filename .. '.log'
        mis_network.log_net_url = mis_config.s_log_net_url
        mis_network.log_net_remote(s_filePath, s_msg)
    else
        local u_fd = get_fd(s_filename)
        if not u_fd then return end
        u_fd:write(s_msg .. '\n')
    end
end

function this.remote_pure_day(s_filename, s_msg)
    local s_localtime = ngx.localtime()
    s_filename = s_filename .. '_' .. s_localtime:match('(.+) ')

    if  mis_config.s_log_net_url then
        local s_filePath = this.s_remote_path .. s_filename .. '.log'
        mis_network.log_net_url = mis_config.s_log_net_url
        mis_network.log_net_remote(s_filePath, s_msg)
    else
        local u_fd = get_fd(s_filename)
        if not u_fd then return end
        u_fd:write(s_msg .. '\n')
    end
end

local to_str = function( v )
    local t_ = type(v)
    if  t_ == 'string' or t_ == 'number' then
        return v
    elseif t_ == 'nil' then
        return 'nil'
    elseif  t_ == 'boolean' then
        if  v then
            return 'true'
        else
            return 'false'
        end
    elseif t_ == 'table' then
        return table.tostring(v)
    elseif v == ngx.null then
        return "not_found_ngx_null"
    else
        return tostring(v)
    end
end

function this.print(s_filename, ...)
    local s_localtime = ngx.localtime()
    s_filename = s_filename .. '_' .. s_localtime:match('(.+) ')

    local u_fd = get_fd(s_filename)
    if not u_fd then return end
    s_localtime = '[' .. s_localtime .. ']'
    local new_txt =s_localtime..'|'..(ngx.ctx.t_params.s_remoteAddr or ngx.ctx.xff or ngx.var.remote_addr or "nil")
    
    for i = 1, select("#", ...) do
        local arg_ = select(i, ...)
        new_txt=new_txt..'|'..to_str(arg_)
    end

    u_fd:write(new_txt .. '\n')

end

return this